﻿using System;
using System.Collections.Generic;
using System.Text;

namespace SOM.Database
{
  public class Connector : SOM.Interfaces.Helper.IDatabaseMethods
  {
    public Connector()
    {
      
    }

    private Dictionary<string, string> _Scheme = new Dictionary<string, string>();

    string ArrayToString(Array arr)
    {
      StringBuilder sb = new StringBuilder();
      bool first = true;
        string tmp = string.Empty;
      foreach (var obj in arr)
      {
        sb.Append(tmp+obj.ToString());
        if (first)
        {
          first = false;
          tmp = ";";
        }
      }
      return sb.ToString();
    }

    public void SendToDatabase<T>(object obj, string server, string table, string SchemeFilePath = "")
    {
      string Name = string.Empty;
      if (!string.IsNullOrEmpty(SchemeFilePath))
      {
        fillScheme(SchemeFilePath);
      }
      Dictionary<string, object> dic = new Dictionary<string, object>();
      using (System.IO.StreamWriter sw = new System.IO.StreamWriter(server,false,System.Text.Encoding.UTF8,512))
      {

        if (obj.GetType().IsAssignableFrom(typeof(System.Collections.Generic.IList<>)) || obj.GetType().Namespace.Contains("SOM.Lists"))
        {

          foreach (var obj1 in ((System.Collections.Generic.List<T>)obj))
          {
            foreach (System.Reflection.PropertyInfo p in obj1.GetType().GetProperties())
            {
              bool run = true;
              foreach (var att in p.GetCustomAttributes(false))
              {
                if (!(att.GetType() == typeof(System.Xml.Serialization.XmlIgnoreAttribute)) && ((att.GetType() == typeof(System.Runtime.InteropServices.ComVisibleAttribute))))
                {
                  if (((System.Runtime.InteropServices.ComVisibleAttribute)att).Value)
                  {
                    run = true;
                    break;
                  }
                  else
                    run = false;
                }
                else
                {
                  run = false;
                }
              }
              if (run)
              {
                
                try {
                  if (_Scheme.Count > 0)
                  {
                    if (_Scheme.ContainsKey(p.Name))
                    {
                      Name = _Scheme[p.Name];
                    }
                    else
                    {
                      Name = p.Name;
                    }
                  }
                  else
                  {
                    Name = p.Name;
                  }
                  //sw.WriteLine(p.Name + ": " + obj1.GetType().GetProperty(p.Name).GetValue(obj1, null).ToString());
                    dic.Add(Name, obj1.GetType().GetProperty(p.Name).GetValue(obj1, null));
                  
                }
                catch { }
              }
            }
            StringBuilder Names = new StringBuilder();
            StringBuilder Values = new StringBuilder();
            bool first = true;
            string tmp = string.Empty;
            foreach (KeyValuePair<string, object> kv in dic)
            {
              try
              {
                Names.Append(tmp + kv.Key);
                if (kv.Value.GetType().IsAssignableFrom(typeof(string)))
                {
                  Values.Append(tmp + "'" + kv.Value + "'");
                }
                else if (kv.Value.GetType().IsArray)
                {
                  Values.Append(tmp + "'" + ArrayToString((Array)kv.Value) + "'");
                }
                else if (kv.Value.GetType().IsAssignableFrom(typeof(SOM.Helper.Types.Point3d)))
                {
                  SOM.Helper.Types.Point3d po = (SOM.Helper.Types.Point3d)kv.Value;
                  Values.Append("'" + po.X.ToString() + "@" + po.Y.ToString() + "@" + po.Z.ToString() + "'");
                }
                else
                {
                  Values.Append(tmp + kv.Value);
                }
              }
              catch
              {
                Names.Remove(Names.Length - 1 - tmp.Length - kv.Key.Length, tmp.Length + kv.Key.Length);
              }
                
              if (first)
              {
                first = false;
                tmp = ",";
              }
            }
            sw.WriteLine(string.Format("INSERT INTO " + table + " ({0}) VALUES ({1});", Names.ToString(), Values.ToString()));
            //sw.WriteLine();
            //sw.WriteLine();
          }
        }
        else
        {
          bool first = true;
          string tmp = string.Empty;
          StringBuilder Names = new StringBuilder();
          StringBuilder Values = new StringBuilder();
          foreach (System.Reflection.PropertyInfo p in obj.GetType().GetProperties())
          {
            bool run = true;
            foreach (var att in p.GetCustomAttributes(false))
            {
              if (!(att.GetType() == typeof(System.Xml.Serialization.XmlIgnoreAttribute)) && ((att.GetType() == typeof(System.Runtime.InteropServices.ComVisibleAttribute))))
              {
                if (((System.Runtime.InteropServices.ComVisibleAttribute)att).Value)
                {
                  run = true;
                  break;
                }
                else
                  run = false;
              }
              else
              {
                run = false;
              }
            }
            if (run)
            {
              try { //sw.WriteLine(p.Name + ": " + obj.GetType().GetProperty(p.Name).GetValue(obj, null).ToString());
                if (_Scheme.Count > 0)
                {
                  if (_Scheme.ContainsKey(p.Name))
                  {
                    Name = _Scheme[p.Name];
                  }
                  else
                  {
                    Name = p.Name;
                  }
                }
                else
                {
                  Name = p.Name;
                }
              Names.Append(tmp + Name);

                if (obj.GetType().GetProperty(p.Name).GetValue(obj, null).GetType().IsAssignableFrom(typeof(string)))
                {
                  Values.Append(tmp + "'" + obj.GetType().GetProperty(p.Name).GetValue(obj, null) + "'");
                }
                else if (obj.GetType().GetProperty(p.Name).GetValue(obj, null).GetType().IsArray)
                {
                  Values.Append(tmp + "'" + ArrayToString((Array)obj.GetType().GetProperty(p.Name).GetValue(obj, null)) + "'");
                }
                else
                {
                  Values.Append(tmp + obj.GetType().GetProperty(p.Name).GetValue(obj, null));
                }

                if (first)
                {
                  tmp = ",";
                  first = false;
                }

                
              }
              catch
              {
                Names.Remove(Names.Length - 1 - tmp.Length - Name.Length, tmp.Length + Name.Length);
              }
            }
          }
          sw.WriteLine(string.Format("INSERT INTO " + table + " ({0}) VALUES ({1});", Names.ToString(), Values.ToString()));
        }
        }
      
    }
    public object GetFromDatabase<T>(string server, int ID, string table, string SchemeFilePath = "")
    {
      if (!string.IsNullOrEmpty(SchemeFilePath))
      {
        fillScheme(SchemeFilePath);
      }
      return 0;
    }

    void fillScheme(string SchemeFilePath)
    {
      if (System.IO.File.Exists(SchemeFilePath))
      {
        using (System.IO.StreamReader sr = new System.IO.StreamReader(SchemeFilePath, System.Text.Encoding.UTF8))
        {
          string tmp = string.Empty;
          string[] tmpArr;
          do
          {
            tmp = sr.ReadLine();

            if (!string.IsNullOrEmpty(tmp) && tmp.Contains("::"))
            {
              tmpArr = System.Text.RegularExpressions.Regex.Split(tmp, System.Text.RegularExpressions.Regex.Escape("::"));
              if (tmpArr.Length == 2)
              {
                _Scheme.Add(tmpArr[0], tmpArr[1]);
              }
              tmpArr = null;
            }
          } while (!sr.EndOfStream);
        }
      }
    }
  }
}
